package com.huike.task;

import com.huike.domain.business.dto.BusinessCountDTO;
import com.huike.domain.clues.dto.ClueCountDTO;
import com.huike.domain.contract.dto.ContractCountDTO;
import com.huike.domain.contract.dto.ContractMoneyDTO;
import com.huike.domain.report.vo.DetailReportVO;
import com.huike.mapper.SysUserMapper;
import com.huike.mapper.TbBusinessMapper;
import com.huike.mapper.TbClueMapper;
import com.huike.mapper.TbContractMapper;
import com.huike.utils.EmailUtils;
import freemarker.template.Configuration;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class MonthExcelDetailReportTask {

    @Autowired
    private TbClueMapper clueMapper;
    @Autowired
    private TbBusinessMapper businessMapper;
    @Autowired
    private TbContractMapper contractMapper;
    @Autowired
    private Configuration configuration;
    @Autowired
    private EmailUtils emailUtils;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Value("${spring.mail.username}")
    private String from; //发件人


    @Scheduled(cron = "0/30 * * * * ?")
    public void sendMonthDetailEmail() throws Exception {

        //1. 本月的开始/结束时间
        LocalDate begin = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
        LocalDate end = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());

        //1.1 获取每一天
        List<String> dateList =
                begin.datesUntil(end.plusDays(1)).
                        map(localDate -> localDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))).collect(Collectors.toList());

        //2. 查询数据库获取指定原始数据 . - 线索 , 商机 , 合同 , 销售额
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

        //2.1 获取每一天的线索数量
        List<ClueCountDTO> clueCountDTOList = clueMapper.countByEveryDay(beginTime, endTime);
        Map<String, Integer> clueDataMap = clueCountDTOList.stream().collect(Collectors.toMap(ClueCountDTO::getClueDate, ClueCountDTO::getClueCount));

        //2.2 获取每一天的商机数量
        List<BusinessCountDTO> businessCountDTOList = businessMapper.countByEveryDay(beginTime, endTime);
        Map<String, Integer> businessDataMap = businessCountDTOList.stream().collect(Collectors.toMap(BusinessCountDTO::getBusinessDate, BusinessCountDTO::getBusinessCount));

        //2.3 获取每一天的合同数量
        List<ContractCountDTO> contractCountDTOList = contractMapper.countByEveryDay(beginTime, endTime);
        Map<String, Integer> contractDataMap = contractCountDTOList.stream().collect(Collectors.toMap(ContractCountDTO::getContractDate, ContractCountDTO::getContractCount));

        //2.4 获取每一天的销售额
        List<ContractMoneyDTO> contractMoneyDTOList = contractMapper.sumMoneyByEveryDay(beginTime, endTime);
        Map<String, Double> contractMoneyMap = contractMoneyDTOList.stream().collect(Collectors.toMap(ContractMoneyDTO::getContractDate, ContractMoneyDTO::getContractMoney));

        //3. 构建数据模型 -- 概要列表
        String dateRange = "时间区间: " + begin + "biu~" + end;
        Integer totalClue = clueCountDTOList.stream().map(ClueCountDTO::getClueCount).reduce(0, Integer::sum);
        Integer totalBusiness = businessCountDTOList.stream().map(BusinessCountDTO::getBusinessCount).reduce(0, Integer::sum);
        Integer totalContract = contractCountDTOList.stream().map(ContractCountDTO::getContractCount).reduce(0, Integer::sum);
        Double totalContractMoney = contractMoneyDTOList.stream().map(ContractMoneyDTO::getContractMoney).reduce(0.0, Double::sum);

        //4. 构建数据模型 -- 明细列表
        List<DetailReportVO> reportVOList = dateList.stream().map(date -> {
            return DetailReportVO.builder()
                    .date(date)
                    .newClueCount(clueDataMap.get(date) == null ? 0 : clueDataMap.get(date))
                    .newBusinessCount(businessDataMap.get(date) == null ? 0 : businessDataMap.get(date))
                    .newContractCount(contractDataMap.get(date) == null ? 0 : contractDataMap.get(date))
                    .saleMoney(contractMoneyMap.get(date) == null ? 0.0 : contractMoneyMap.get(date))
                    .build();
        }).collect(Collectors.toList());

        //5. 加载模板文件, 基于POI发送邮件
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("templates/客达天下-月度运营统计.xlsx");
        Workbook workbook = new XSSFWorkbook(inputStream);
        Sheet sheet = workbook.getSheetAt(0);

        //6. 定位单元格, 数据填充
        //6.1 概览数据
        sheet.getRow(1).getCell(1).setCellValue(dateRange);
        sheet.getRow(3).getCell(1).setCellValue(totalClue);
        sheet.getRow(3).getCell(2).setCellValue(totalBusiness);
        sheet.getRow(3).getCell(3).setCellValue(totalContract);
        sheet.getRow(3).getCell(4).setCellValue(totalContractMoney);

        //6.2 明细数据
        for (int i = 0; i < reportVOList.size(); i++) {
            Row row = sheet.getRow(5 + i);
            DetailReportVO reportVO = reportVOList.get(i);
            row.getCell(0).setCellValue(i);
            row.getCell(1).setCellValue(reportVO.getDate());
            row.getCell(2).setCellValue(reportVO.getNewClueCount());
            row.getCell(3).setCellValue(reportVO.getNewBusinessCount());
            row.getCell(4).setCellValue(reportVO.getNewContractCount());
            row.getCell(5).setCellValue(reportVO.getSaleMoney());
        }

        //7 释放资源
        String email = sysUserMapper.selectUserById(1L).getEmail();
        String subject = "月度运营统计报表";
        String text = "吊毛";
        String fileName = "月度运营统计报表";
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        workbook.write(outputStream);
        emailUtils.sendMailWithAttachment(from, email, subject, text, fileName, outputStream.toByteArray());
    }
}
